<template>
  <div>
    <!-- http-request:覆盖默认的上传行为，可以自定义上传的实现 -->
    <el-upload
      action="#"
      :file-list="fileList"
      list-type="picture-card"
      :on-preview="handlePictureCardPreview"
      :on-remove="handleRemove"
      :on-change="handleChange"
      :http-request="handleUpload"
      :class="{ disabled: overLimit }"
      :limit="imgLimit"
      :before-upload="handleBeforeUpload"
    >
      <i class="el-icon-plus" />
    </el-upload>
    <el-progress
      :percentage="percent"
      style="width: 170px"
      v-if="showProgress"
    />
    <el-dialog :visible.sync="dialogVisible" title="图片预览">
      <!-- 显示出图片 -->
      <img width="100%" :src="dialogImageUrl" alt="" />
    </el-dialog>
  </div>
</template>

<script>
import COS from "cos-js-sdk-v5";
// 创建一个全局的cos
const cos = new COS({
  SecretId: "AKIDpMuPm2B9tOelkt3A9vSlqhN0c2DB0ylQ",
  SecretKey: "fLsALI8nJdljbNxaCi4MXVlFYgcOyR5Z",
});
export default {
  props: {
    imgLimit: {
      type: Number,
      default: 1,
    },
    //  针对v-model语法糖 实现:value
    value: {
      type: Array,
      //默认是数组的话必须以函数形式导出
      default: () => [],
    },
  },
  data() {
    return {
      // fileList是一个对象数组
      fileList: this.value || [], //当前以及完成上传/选择的文件列表
      dialogImageUrl: "",
      dialogVisible: false,
      showProgress: false,
      percent: 0,
    };
  },
  watch: {
    value(newVal) {
      // 把变化后的value赋值给fileList
      this.fileList = newVal;
    },
  },
  computed: {
    overLimit() {
      return this.fileList.length >= this.imgLimit
    },
  },
  methods: {
    handleRemove(file, fileList) {
      // 图片溢出以后回调的钩子函数
      // file:被移除的文件对象
      // 从data的fileList中移除file对象
      // 因为overLimit计算属性，用的是data中的fileList的长度
      // console.log(fileList);
      // console.log(file, fileList);
      this.fileList = [...fileList];
      // 针对v-model的语法糖实现@input
      this.$emit('input',[...this.fileList])
    },
    handlePictureCardPreview(file) {
      // file是文件对象，包含了文件name和url
      // console.log(file);
      // 让弹出层的img显示
      this.dialogImageUrl = file.url;
      // 让弹窗显示
      this.dialogVisible = true;
    },
    handleChange(file, fileList) {
      // 只要文件发生变化，就会回调on-change钩子函数
      // fileList里面就是当前上传组件以及选择/上传的文件对象列表
      // 所以，我们只需要监听fileList的变化，就知道当前以及有几个文件上传/被选中
      // console.log(fileList);
      this.fileList = [...fileList];
    },
    //  文件上传之前的判断  是否符号需要的要求
    handleBeforeUpload(file) {
      // file对象包含的字段有uid，name，type：文件的类型和格式，size是文件的大小尺寸，单位是b
      const validTypes = ["image/jpeg", "image/gif", "image/bmp", "image/png"];
      if (!validTypes.includes(file.type)) {
        this.$message.error("图片格式不正确");
        return false;
      }
      const maxSize = 2 * 1024 * 1024;
      if (file.size >= maxSize) {
        this.$message.error("图片大小最大不能超过2M");
        return false;
      }
    },
    closeProgressDelay(ms = 1000) {
      setTimeout(() => {
        this.showProgress = false;
      }, ms);
    },
    handleUpload(params) {
      // console.log(params);
      // 有文件再上传，没有文件，不处理
      if (!params.file) {
        return;
      }
      const options = {
        Bucket: "hrsass46-1314715336" /* 填入您自己的存储桶，必须字段 */,
        Region: "ap-chengdu" /* 存储桶所在地域，例如ap-beijing，必须字段 */,
        Key: params.file
          .name /* 存储在桶里的对象键（例如1.jpg，a/b/test.txt），必须字段 */,
        Body: params.file /* 必须，上传文件对象，可以是input[type="file"]标签选择本地文件后得到的file对象 */,
        //  进度条
        onProgress: (progressData) => {
          //   console.log(JSON.stringify(progressData));
          // 0.89 => 89%
          this.percent = parseInt(progressData.percent * 100);
        },
      };
      this.showProgress = true;

      cos.putObject(options, (err, data) => {
        //   console.log(err || data);
        // data里面有一个Location，就是图片上传以后的地址，但是没有http前缀
        //  if (err) {
        //    this.$message.error(err.message);
        //    return;
        //  }
        const { statusCode, Location } = data;
        //  if (statusCode !== 200) {
        //    return;
        //  }
        // 简写方法  可以用或(||) 一起写
        if (err || statusCode !== 200) {
          this.$message.error("上传出错了");
          //  关闭进度条
          this.closeProgressDelay();
          return;
        }
        const cosImgUrl = "http://" + Location;
        //   console.log(cosImgUrl);
        //  将本地图片地址替换成cos存储桶里的地址
        this.fileList = this.fileList.map((item) => {
          if (item.uid === params.file.uid) {
            item.url = cosImgUrl;
            // 补一个属性叫update  item里面原来是没有update属性的 补这个属性的目的，是打一个标记
            item.update = true;
          }
          return item;
        });
        //   关闭进度条
        this.closeProgressDelay();
        //  针对v-model语法糖，实现@input
        this.$emit("input", [...this.fileList]);
      });
    },
  },
};
</script>

<style>
.disabled .el-upload--picture-card {
  display: none;
}
</style>